package org.fanximall.erp.product.application.service.impl;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.fanximall.erp.common.page.PageResponse;
import org.fanximall.erp.common.utils.ExceptionUtils;
import org.fanximall.erp.product.application.convert.AttributeConvert;
import org.fanximall.erp.product.application.enums.DictCodeEnum;
import org.fanximall.erp.product.application.req.AttributeItemPageQuery;
import org.fanximall.erp.product.application.req.AttributeValueSaveCommand;
import org.fanximall.erp.product.application.req.ConfAttributeSaveCommand;
import org.fanximall.erp.product.application.resp.AttributeDetailRespDTO;
import org.fanximall.erp.product.application.resp.AttributeItemRespDTO;
import org.fanximall.erp.product.application.service.ConfAttributeService;
import org.fanximall.erp.product.domain.aggregate.AttributeAggregateRoot;
import org.fanximall.erp.product.domain.model.AttributeItemModel;
import org.fanximall.erp.product.domain.model.AttributeValueModel;
import org.fanximall.erp.product.domain.repository.AttributeRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author :  william
 * @version :  V1.0  created in 2024/4/23
 */
@Service
public class ConfAttributeServiceImpl implements ConfAttributeService {

    @Resource
    private AttributeRepository attributeRepository;


    @Resource
    private AttributeConvert attributeConvert;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttribute(ConfAttributeSaveCommand confAttributeSaveCommand) {
        AttributeAggregateRoot attributeAggregateRoot = attributeConvert.attributeItemCommentConvert(confAttributeSaveCommand);
        if (null == confAttributeSaveCommand.getId()) {
            insert(confAttributeSaveCommand, attributeAggregateRoot);
        }else {
            update(confAttributeSaveCommand, attributeAggregateRoot);
        }
    }

    @Override
    public PageResponse<AttributeItemRespDTO> pageQueryAttributeItem(AttributeItemPageQuery attributeItemPageQuery) {
        PageResponse<AttributeItemModel> attributeItemModelPageResponse = attributeRepository.pageQueryAttributeItem(attributeConvert.attributeItemPageQueryConvert(attributeItemPageQuery));
        return PageResponse.<AttributeItemRespDTO>builder()
                .current(attributeItemModelPageResponse.getCurrent())
                .size(attributeItemModelPageResponse.getSize())
                .total(attributeItemModelPageResponse.getTotal())
                .records(attributeConvert.attributeItemRespConvert(attributeItemModelPageResponse.getRecords()))
                .build();
    }

    @Override
    public AttributeDetailRespDTO getAttributeDetailRespDTO(Long attributeItemId) {
        AttributeAggregateRoot attributeByAttributeItemIdAggregateRoot = attributeRepository.getAttributeByAttributeItemId(attributeItemId);
        return attributeConvert.attributeDetailRespDTOConvert(attributeByAttributeItemIdAggregateRoot);
    }


    /**
     * 添加属性信息
     * @param confAttributeSaveCommand 属性信息
     * @param attributeAggregateRoot 属性项信息
     */
    private void insert(ConfAttributeSaveCommand confAttributeSaveCommand, AttributeAggregateRoot attributeAggregateRoot) {
        confAttributeSaveCommand.validateInputMode();
        AttributeItemModel attributeItemModel = attributeAggregateRoot.getAttributeItemModel();
        boolean exist = attributeRepository.existAttributeItem(confAttributeSaveCommand.getAttrItemName(), confAttributeSaveCommand.getAttrType());
        ExceptionUtils.ifTrueThrowVerifyException(exist,"属性已存在,请勿重复添加");
        attributeRepository.saveAttributeItem(attributeItemModel);
        if (!DictCodeEnum.INPUT_MODE_INPUT.getDictCode().equals(confAttributeSaveCommand.getInputMode())){
            List<AttributeValueSaveCommand> attributeValueSaveCommands = confAttributeSaveCommand.getAttributeValueSaveCommands();
            if (CollectionUtils.isNotEmpty(attributeValueSaveCommands)) {
                batchSaveAttributeValue(attributeValueSaveCommands, attributeItemModel.getId());
            }
        }
    }


    /**
     * 更新属性信息
     * @param confAttributeSaveCommand 属性信息
     * @param attributeAggregateRoot 属性项信息
     */
    private void update(ConfAttributeSaveCommand confAttributeSaveCommand, AttributeAggregateRoot attributeAggregateRoot) {
        AttributeItemModel attributeItemModel = attributeAggregateRoot.getAttributeItemModel();
        attributeRepository.updateAttributeItem(attributeItemModel);
        Long attrItemId = confAttributeSaveCommand.getId();
        List<AttributeValueModel> attributeItemValue = ListUtils.emptyIfNull(attributeRepository.getAttributeItemValue(attrItemId));
        List<AttributeValueSaveCommand> attributeValueSaveCommands = ListUtils.emptyIfNull(confAttributeSaveCommand.getAttributeValueSaveCommands());
        // 找出attributeValueSaveCommands中有而attributeItemValue中没有的属性值
        List<AttributeValueSaveCommand> saveAttributeValueList = attributeValueSaveCommands.stream()
                .filter(item -> attributeItemValue.stream()
                        .noneMatch(model -> model.getAttrValue().equals(item.getAttrValue())))
                .collect(Collectors.toList());

        // 找出attributeItemValue中有而attributeValueSaveCommands中没有的属性值的ID
        List<Long> deleteAttributeList = attributeItemValue.stream()
                .filter(item -> attributeValueSaveCommands.stream()
                        .noneMatch(command -> command.getAttrValue().equals(item.getAttrValue())))
                .map(AttributeValueModel::getId)
                .collect(Collectors.toList());

        // TODO: 校验属性是否被使用

        if (CollectionUtils.isNotEmpty(saveAttributeValueList)) {
            batchSaveAttributeValue(saveAttributeValueList, attrItemId);
        }

        if (CollectionUtils.isNotEmpty(deleteAttributeList)) {
            attributeRepository.batchDeleteAttributeValue(deleteAttributeList);
        }
    }


    private void batchSaveAttributeValue(List<AttributeValueSaveCommand> attributeValueSaveCommands, Long attributeItemComment) {
        List<AttributeValueModel> attributeValues = attributeValueSaveCommands.stream().map(
                item -> new AttributeValueModel(attributeItemComment,item.getAttrValue(), item.getSort())).collect(Collectors.toList());
        attributeRepository.batchSaveAttributeValue(attributeValues);
    }


}
